#include "websocket_packet_parsing.h"

int check_websocket_packet_rece_finish(uint8_t *packet, uint32_t len)
{
	uint32_t i = 0;
	uint8_t *fin_rsv = 0;
	uint32_t mask = 0;
	uint32_t paylen = 0;
	uint32_t mask_key = 0;
	uint64_t data_len = 0;
	uint8_t packet_buf[512] = {0};

	for (i = 0; i < len; i++)
	{
		packet_buf[i] = packet[i];
	}

	while (1)
	{
		for (i = 0x80; i <= 0x8F; i++)
		{
			if ((fin_rsv = str_chr(packet_buf, i)))
			{
				break;
			}
		}
		
		if (*fin_rsv != 0)
		{
			mask = *(fin_rsv+1)>>7;
			paylen = *(fin_rsv+1) & 0x7F;
			
			if (paylen < 126)
			{
				data_len = paylen;
			}
			else if (paylen == 126)
			{	
				data_len = *(fin_rsv + 2) << 8;
				data_len += *(fin_rsv + 3);
			}
			else if (paylen == 127)
			{
				for (i = 0; i < 7; i++)
				{
					data_len += *(fin_rsv + 2 + i);
					data_len <<= 8;
				}
				data_len += *(fin_rsv + 2 + i);
			}
			if (paylen < 126)
			{
				if (mask == 0)
				{
					if (*(fin_rsv + 1 + data_len) != 0)
					{
						return 1;
					}
				}
				else
				{
					if (*(fin_rsv + 5 + data_len) != 0)
					{
						return 1;
					}
				}
			}

			if (paylen == 126)
			{
				if (mask == 0)
				{
					if (*(fin_rsv + 3 + data_len) != 0)
					{
						return 1;
					}
				}
				else
				{
					if (*(fin_rsv + 7 + data_len) != 0)
					{
						return 1;
					}
				}
				
			}

			if (paylen == 127)
			{
				if (mask == 0)
				{
					if (*(fin_rsv + 9 + data_len) != 0)
					{
						return 1;
					}
				}
				else
				{
					if (*(fin_rsv + 13 + data_len) != 0)
					{
						return 1;
					}
				}
			}

			return 0;
		}
		else
		{
			return 0;
		}
	}
}

uint32_t get_websocket_packet_content(uint8_t *packet, uint8_t *keyword,uint8_t *buf)
{
	uint32_t i = 0;
	uint8_t *fin_rsv = 0;
	uint8_t Fin_Rsv = 0;
	uint8_t opcode = 0;
	uint8_t mask = 0;
	uint8_t paylen = 0;
	uint32_t mask_key = 0;
	uint32_t extened_paylen = 0;

	while (1)
	{
		for (i = 0x80; i <= 0x8F; i++)
		{
			if ((fin_rsv = str_chr(packet, (uint8_t)i)))
			{
				Fin_Rsv = i;
				break;
			}
		}

		if (*fin_rsv != 0)
		{
			mask = *(fin_rsv + 1) >> 7;
			paylen = *(fin_rsv + 1) & 0x7F;

			if (paylen < 126)
			{
				extened_paylen = paylen;
			}
			else if (paylen == 126)
			{
				extened_paylen = *(fin_rsv + 2) << 8;
				extened_paylen += *(fin_rsv + 3);
			}
			else if (paylen == 127)
			{
				for (i = 0; i < 7; i++)
				{
					extened_paylen += *(fin_rsv + 2 + i);
					extened_paylen <<= 8;
				}
				extened_paylen += *(fin_rsv + 2 + i);
			}
			else
			{
				return GET_NOK;
			}
			if (paylen < 126)
			{
				if (mask == 0)
				{
					break;
				}
				else
				{
					for (i = 0; i < 3; i++)
					{
						mask_key += *(fin_rsv + 2 + i);
						mask_key <<= 8;
					}
					mask_key += *(fin_rsv + 2 + i);
					break;
				}
			}

			if (paylen == 126)
			{
				if (mask == 0)
				{
					break;
				}
				else
				{
					for (i = 0; i < 3; i++)
					{
						mask_key += *(fin_rsv + 4 + i);
						mask_key <<= 8;
					}
					mask_key += *(fin_rsv + 4 + i);
					break;
				}
			}

			if (paylen == 127)
			{
				if (mask == 0)
				{
					break;
				}
				else
				{
					for (i = 0; i < 3; i++)
					{
						mask_key += *(fin_rsv + 10 + i);
						mask_key <<= 8;
					}
					mask_key += *(fin_rsv + 10 + i);
					break;
				}
			}
		}
		else
		{
			return GET_NOK;
		}
	}

	if (str_str(keyword, WEBSOCKET_FIN_RSV))
	{
		return Fin_Rsv;
	}
	else if(str_str(keyword, WEBSOCKET_OPCODE))
	{
		opcode = Fin_Rsv & 0x0F;
		return opcode;
	}
	else if (str_str(keyword, WEBSOCKET_MASK))
	{
		return mask;
	}
	else if (str_str(keyword, WEBSOCKET_PAYLOAD_LEN))
	{
		return paylen;
	}
	else if (str_str(keyword, WEBSOCKET_MASK_KEY))
	{
		return mask_key;
	}
	else if (str_str(keyword, WEBSOCKET_EXTENDED_PAYLEN))
	{
		return extened_paylen;
	}
	else if (str_str(keyword, WEB_DATA))
	{
		if (paylen < 126)
		{
			if (mask == 0)
			{
				Strncpy(buf, fin_rsv+2, extened_paylen);
			}
			else
			{
				Strncpy(buf, fin_rsv+6, extened_paylen);
			}
			return GET_OK;
		}
		else if (paylen == 126)
		{
			if (mask == 0)
			{
				Strncpy(buf, fin_rsv + 4, extened_paylen);
			}
			else
			{
				Strncpy(buf, fin_rsv+8, extened_paylen);
			}
			return GET_OK;
		}
		else if (paylen == 127)
		{
			if (mask == 0)
			{
				Strncpy(buf, fin_rsv + 10, extened_paylen);
			}
			else
			{
				Strncpy(buf, fin_rsv + 14, extened_paylen);
			}
			return GET_OK;
		}
	}

	return GET_NOK;
}

uint32_t get_websocket_packet_head(uint8_t *packet, uint8_t *keyword)
{
	uint32_t ret;

	ret = get_websocket_packet_content(packet,keyword, 0);

	return ret;
}

int get_websocket_packet_data(uint8_t *packet, uint8_t *buf)
{
	get_websocket_packet_content(packet,WEB_DATA,buf);
	if (*buf)
	{
		return GET_NOK;
	}
	else
	{
		return GET_OK;
	}
}

